import runtimeType from '../../sys/runtimeType';
import config from '../../sys/config';
import http from '../http';
import calldeal from '../calldeal';
import { showLoading } from '../prompt';

/**
 * 【异步方法】upload资源上传
 * @description upload资源上传，参数详情请查看配置文件focus.config.js
 * @param parameter 方法参数
 */
function upload(parameter) {
    
    // ------------------------------------------------ 参数预处理
    // 获取当前运行环境
    let runType = runtimeType();
    // 获取配置文件upload信息
    let config_file = config('get').network;
    // 合并 配置文件参数、主动传入参数
    let config_result = Object.assign({}, config_file, parameter);
    // 成品请求地址 = 请求地址头 + api地址
    if (config_result["openHttphead"] == true) { config_result["url"] = http('get') + config_result["url"]; }
    
    // ------------------------------------------------ 上传进度初始化
    // 总需要的进度 = 100% * 上传文件数量
    let num_progress_total = Math.round(100 * config_result["files"].length);
    // 临时保存表：各文件上传进度
    let arr_progress_file = [];
    // 临时保存表：各文件上传结果
    let arr_upResult_file = [];

    // ------------------------------------------------ 通用调用事件
    /** 成功/失败回调逻辑处理 */
    function deal_callback(data_backC) {
        // 是否全部文件上传工作结束
        let bool_uploadAll = true;
        // 是否存在失败的上传任务
        let bool_hadFailUp = false;
        // 循环文件数量长度的次数
        for (let i = 0; i < config_result["files"].length; i++) {
            // 如果列表元素不存在，说明还没有结束上传工作
            if (arr_upResult_file[i] === undefined) { bool_uploadAll = false; }
            // 如果请求成功标识为否，说明这个上传失败了
            else if (arr_upResult_file[i].isSuccess != true) { bool_hadFailUp = true; }
        }
        // 只有上传工作执行完毕，才执行
        if (bool_uploadAll == true)
        {
            // 如果是请求成功
            if (bool_hadFailUp != true) {
                // 全局的成功方法调用结果
                let result_fileSuccess = true;
                // 配置文件成功方法
                if (config_file && config_file.success) { result_fileSuccess = config_file.success(data_backC); }
                // 主动参数的失败方法
                if (result_fileSuccess === false && parameter && parameter.fail) { parameter.fail(data_backC); }
                // 主动参数的成功方法
                else if (parameter && parameter.success) { parameter.success(data_backC); }
            }
            // 如果是请求失败
            else {
                // 全局的失败方法调用结果
                let result_fileFail = true;
                // 配置文件失败方法
                if (config_file && config_file.fail) { result_fileFail = config_file.fail(data_backC); }
                // 主动参数的失败方法
                if (result_fileFail !== false && parameter && parameter.fail) { parameter.fail(data_backC); }
            }
        }
    };
    /** 进度变化监听回调逻辑处理，参数：data_backC-要回调的数据 */
    function deal_progress(data_backC) {
        // 全局的进度监听方法调用结果
        let result_fileProgress = true;
        // 配置文件成功方法
        if (config_file && config_file.progress) { result_fileProgress = config_file.progress(data_backC); }
        // 主动参数的成功方法
        if (result_fileProgress!==false && parameter && parameter.progress) { parameter.progress(data_backC); }
    }

    // ------------------------------------------------ header请求头
    // 要传递请求头 编辑
    let req_header = {};
    // 1. 配置文件header加入到此数据
    if (config_file["header"]) { for (let key in config_file["header"]) { req_header[key] = config_file.header[key]; } }
    // 2. 主动传递参数的header覆盖到此数据
    if (config_result["header"]) { for (let key in config_result["header"]) { req_header[key] = config_result.header[key]; } }
    // 3. 去除其中的 Content-Type
    delete req_header["Content-Type"]; delete req_header["content-type"];

    // ------------------------------------------------ 地址栏传输数据
    // 请求地址取出
    let str_url_api = config_result["url"];
    // 地址栏数据添加
    for (let key in config_result["pathData"]) { str_url_api += '/' + config_result.pathData[key]; }
    
    // ------------------------------------------------ 循环待上传文件列表
    // 显示"下载中"提示弹框
    if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' 0%'); }
    // 循环要上传的文件
    for (let i = 0; i < config_result["files"].length; i++)
    {
        // 节点 - 一个文件信息对象
        let ele_file = config_result["files"][i];
        // 初始化此文件的上传进度
        let num_index = parseInt(i);
        arr_progress_file[num_index] = 0;
        
        // ------------------------------------------------ 调用上传请求api
        // 如果是“非UNI”环境
        if (runType == 'NOT-UNI')
        {
            // 要发送的数据封装(上传数据表单化处理)
            let myform = new FormData();
            // 加入文件字段
            myform.append(ele_file["name"], ele_file["data"]);
            // 加入其它额外字段
            for (let key in config_result["data"]) { myform.append(key, config_result["data"][key]); }

            // 创建 XMLHttpRequest 对象
            let xhr = new XMLHttpRequest();
            // 初始化实例对象
            xhr.open("POST", str_url_api, true);
            // 请求头数据赋值
            for (let k in req_header) { xhr.setRequestHeader(k, req_header[k]); }
            // 指定请求超时时间
            xhr.timeout = config_result["timeout"];
            // 接收完服务器返回数据后，进行的数据类型处理方式
            xhr.responseType = config_result["responseType"];

            // 获取响应头公共方法
            let fun_getResponseHeader = () => {
                // 结果响应头
                let obj_resHeaders = {};
                // 获取响应头
                let str_resHeaders = xhr.getAllResponseHeaders();
                // 如果存在响应头
                if (str_resHeaders) {
                    // 将响应头转换为数组
                    var arr_resHeaders = str_resHeaders.trim().split(/[\r\n]+/);
                    // 循环响应头数组
                    arr_resHeaders.forEach((line) => {
                        // 按照冒号再分割
                        var parts = line.split(': ');
                        // 头的名称
                        var header = parts.shift();
                        // 头的值
                        var value = parts.join(': ');
                        // 将头添加到结果对象
                        obj_resHeaders[header] = value;
                    });
                }
                // 返回处理后的响应头
                return obj_resHeaders;
            };

            // 上传进度回调
            xhr.addEventListener('progress', (ev) => {
                // 检测是否真实上传
                if (ev.lengthComputable) 
                {
                    // 此文件上传进度 赋值
                    arr_progress_file[num_index] = Math.floor(ev.loaded / ev.total * 1000) / 10; // 百分比，如： 53.8
                    // 已经完成的上传进度
                    let num_progress_files = 0;
                    // 各文件上传进度求和
                    arr_progress_file.forEach((val) => { num_progress_files += val; });
                    // 计算当前已有的上传进度
                    let num_progress_already = Math.floor(num_progress_files / num_progress_total * 100);
                    // 进度显示框
                    if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' ' + num_progress_already + '%'); }
                    // 传回给监听方法的数据
                    let backThis = {
                        percentage: num_progress_already, // 总上传进度百分比
                        total: num_progress_total, // 要处理数据的总量
                        over: num_progress_files, // 已经处理完成的数据的量
                    };
                    // 配置文件监听回调
                    deal_progress(backThis);
                }
            });
            // 请求超时监听
            xhr.addEventListener('timeout', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, 0, obj_resHeaders, null, 'timeout');
                // 添加到 各文件上传结果临时表
                arr_upResult_file[num_index] = data_back;
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求失败监听
            xhr.addEventListener('error', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, xhr.status, obj_resHeaders, xhr.response);
                // 添加到 各文件上传结果临时表
                arr_upResult_file[num_index] = data_back;
                // 回调逻辑处理
                deal_callback(data_back);
            });
            // 请求成功监听
            xhr.addEventListener('load', () => {
                // 获取响应头
                let obj_resHeaders = fun_getResponseHeader();
                // 获取接口请求结果对象
                let data_back = calldeal(config_result, xhr.status, obj_resHeaders, xhr.response);
                // 添加到 各文件上传结果临时表
                arr_upResult_file[num_index] = data_back;
                // 回调逻辑处理
                deal_callback(data_back);
            });
            
            // 发送请求
            xhr.send(myform);
        }
        // 如果是UNI环境
        else {
            // 官方发起上传api
            let uploadTask = uni.uploadFile({
                url: str_url_api,
                name: ele_file["name"],
                filePath: ele_file["data"],
                formData: config_result["data"],
                header: req_header,
                timeout: config_result["timeout"],
                fail: (resD) => {
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, 0, {}, resD, 'unifail');
                    // 添加到 各文件上传结果临时表
                    arr_upResult_file[num_index] = data_back;
                    // 回调逻辑处理
                    deal_callback(data_back);
                },
                success: (resD) => {
                    // 获取接口请求结果对象
                    let data_back = calldeal(config_result, resD.statusCode, {}, resD.data);
                    // 添加到 各文件上传结果临时表
                    arr_upResult_file[num_index] = data_back;
                    // 回调逻辑处理
                    deal_callback(data_back);
                },
            });
            
            // 上传进度监听
            uploadTask.onProgressUpdate((TaskD) => {
                // 此文件上传进度 赋值
                arr_progress_file[num_index] = TaskD.progress;
                // 已经完成的上传进度
                let num_progress_files = 0;
                // 各文件上传进度求和
                arr_progress_file.forEach((val) => { num_progress_files += val; });
                // 计算当前已有的上传进度
                let num_progress_already = Math.floor(num_progress_files / num_progress_total * 100); 
                // 进度显示框
                if (config_result["loadingText"] != null) { showLoading(config_result["loadingText"] + ' ' + num_progress_already + '%'); }
                // 传回给监听方法的数据
                let backThis = {
                    percentage: num_progress_already, // 总上传进度百分比
                    total: num_progress_total, // 要处理数据的总量
                    over: num_progress_files, // 已经处理完成的数据的量
                };
                // 配置文件监听回调
                deal_progress(backThis);
            });
        }
        
    }
    
}

export default upload;